package interfaces

import (
	"deploy/interfaces/db"
	"deploy/utils"
	"fmt"
	"github.com/gorilla/websocket"
	"log"
	"strings"
	"sync"
)

// 客户端
type Client struct {
	ws         *websocket.Conn // 连接套接字
	Id         int             // 用户身份信息
	Name       string          // 用户身份信息
	mutex      sync.Mutex      // 避免重复关闭管道
	isClosed   bool            // 链接是否关闭
	closeChan  chan byte       // 关闭通知
	outChan    chan []byte     // 发送数据
	server     *Server
	Ip         string
	SyncChan   chan interface{} //需要同步处理的数据
	ServerType float64
	// ConfChan chan interface{} TODO 缘分的bug，如果有机会 bug就出来了
}

// 新建client
func NewClient(ws *websocket.Conn, id int, name string, server *Server) *Client {
	ipAddr := ws.RemoteAddr().String()
	ip := strings.Split(ipAddr, ":")[0]
	return &Client{ws: ws,
		Id:        id,
		Name:      name,
		server:    server,
		isClosed:  false,
		closeChan: make(chan byte),
		outChan:   make(chan []byte),
		Ip:        ip,
		SyncChan:  make(chan interface{}),
	}
}

// 从用户的outchan读取数据 向这个client发送数据
func (c *Client) Send() {
	for {
		msg := <-c.outChan
		// log.Println("server 发送数据",string(msg))
		if err := c.ws.WriteMessage(websocket.BinaryMessage, msg); err != nil {
			log.Println("send msg err:", err.Error())
		}
	}
}

// 接收这个用户的数据 解码并调用数据处理的方法
func (c *Client) Receive() {
	for {
		_, buf, err := c.ws.ReadMessage()
		if err != nil {
			fmt.Println("读取数据出错:", err.Error())
			c.isClosed = true
			c.mutex.Lock()
			// 查找相关的实例
			obj := db.Instance{}
			err = c.server.Db.GetInstanceByIp(c.Ip, &obj)
			if err != nil {
				log.Println(fmt.Sprintf("查找主机IP:%s Hostname:%s 失败,不更新数据库的离线状态", c.Ip, c.Name))
			} else {
				// 更新实例为离线状态
				err = c.server.Db.UpdateInstanceById(obj.ID, map[string]interface{}{"is_online": false})
				if err != nil {
					s := fmt.Sprintf("更新实例 %s Haddr %s 状态为离线时失败:%s", obj.HostName, obj.HardwareAddr, err.Error())
					log.Println(s)
					return
				}
			}
			c.ws.Close()
			delete(c.server.OnlineClientMap, c.Name)
			c.mutex.Unlock()
			return
		}
		//log.Println("数据类型为：",n)
		//log.Println("数据长度为：",len(buf))
		//log.Println("server收到数据",string(buf))
		m := utils.NewRequest(buf, []byte("12345678"))

		if m == nil {
			log.Println("server解析消息出错了```")
			continue
		}
		c.server.Domsg(c, *m)
	}
}
